package com.lingxu.base.common.util;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

public class FileUtil {


	/**
	 * 文件复制
	 * @param source 源文件
	 * @param dest 需要复制的文件
	 * @throws IOException
	 */
    public static synchronized void copyFileUsingFileChannels(File source, File dest) throws IOException {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } finally {
            inputChannel.close();
            outputChannel.close();
        }
    }

    /**
     * 获取文档的编码格式 解决文件编码不一致时读取中文乱码的问题 -wangtao
     *
     * @param bt
     * @return
     * @throws Exception
     */
    public static String getCharset(byte[] bt) throws Exception {
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        try {
            boolean checked = false;
            BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(bt));
            bis.mark(0);
            int read = bis.read(first3Bytes, 0, 3);
            if (read == -1) {
                return charset; // 文件编码为 ANSI
            } else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
                charset = "UTF-16LE"; // 文件编码为 Unicode
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
                charset = "UTF-16BE"; // 文件编码为 Unicode big endian
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB
                    && first3Bytes[2] == (byte) 0xBF) {
                charset = "UTF-8"; // 文件编码为 UTF-8
                checked = true;
            } else if (!isGB2312(bt)) {
                charset = "GB2312"; // 文件编码为 GB2312
                checked = true;
            }
            bis.reset();
            if (!checked) {
                while ((read = bis.read()) != -1) {
                    if (read >= 0xF0)
                        break;
                    if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的，也算是GBK
                        break;
                    if (0xC0 <= read && read <= 0xDF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)
                            // (0x80
                            // - 0xBF),也可能在GB编码内
                            continue;
                        else
                            break;
                    } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错，但是几率较小
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                charset = "UTF-8";
                                break;
                            } else
                                break;
                        } else
                            break;
                    }
                }
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return charset;
    }

    /**
     * 判断文件及其目录是否存在，若不存在则创建文件及目录
     *
     * @param filepath
     * @return
     * @throws Exception
     */
    public static synchronized File checkExist(String filepath) throws IOException {

        File file = new File(filepath);

        if (file.exists()) {// 判断文件目录的存在
//			System.out.println(file.getPath() + "文件夹存在！");
            if (file.isDirectory()) {// 判断文件的存在性
//				System.out.println(file.getName() + "文件存在！");
            } else {

                file.createNewFile();// 创建文件
//				System.out.println(file.getName() + "文件不存在，创建文件成功！");
            }
        } else {
//			System.out.println(file.getPath() + "文件夹不存在！");
            File file2 = new File(file.getParent());
            file2.mkdirs();
//			System.out.println(file.getPath() + "创建文件夹成功！");
            if (file.isDirectory()) {
//				System.out.println(file.getName() + "文件存在！");
            } else {
                file.createNewFile();// 创建文件
//				System.out.println(file.getName() + "文件不存在，创建文件成功！");
            }
        }
        return file;

    }

    /**
     * 根据文件路径拉取该文件或者该文件夹下的所有文件
     *
     * @param filepath
     * @return
     */
    public static List<File> readAllFile(String filepath) {
        List<File> listname = new ArrayList<File>();
        File file = new File(filepath);
        if (!file.isDirectory() && file.isFile()) {
            // 文件
            listname.add(file);
        } else if (file.isDirectory()) {
//			System.out.println("文件夹");
            String[] filelist = file.list();
//			System.out.println("共有文件夹" + filelist.length + "个");
            for (int i = 0; i < filelist.length; i++) {
//				System.out.println("抽取第" + (i + 1) + "个文件夹");
                File readfile = new File(filepath + System.getProperty("file.separator") + filelist[i]);
                if (!readfile.isDirectory()) {
                    listname.add(readfile);
                } else if (readfile.isDirectory()) {
                    List<File> flist = new ArrayList<File>();
                    flist = readAllFile(filepath + System.getProperty("file.separator") + filelist[i]);// 递归
                    for (File f : flist) {
                        listname.add(f);
                    }
                }
            }
        }
        return listname;
    }

    /**
     * 读取文件内容
     *
     * @param file
     * @return
     */
    public static synchronized String readTxt(File file,String charset) {
        InputStream is = null;
        InputStream input = null;
        byte[] bt = null;
        StringBuffer sb = new StringBuffer();
        BufferedReader br = null;
        try {

            input = new FileInputStream(file);
            bt = new byte[input.available()];
            input.read(bt);

            is = new ByteArrayInputStream(bt);
            br = new BufferedReader(new InputStreamReader(is, charset));// 构造一个BufferedReader类来读取文件
            String s = null;
            while ((s = br.readLine()) != null) {// 使用readLine方法，一次读一行
                sb.append(s);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();

    }

    /**
     * * 对于gb2312来讲,首字节码位从0×81至0×FE，尾字节码位分别是0×40至0×FE * *
     */
    public static synchronized boolean isGB2312(byte[] b) {
        String str = new String(b);
        char[] chars = str.toCharArray();
        boolean isGB2312 = false;
        for (int i = 0; i < chars.length; i++) {
            byte[] bytes = ("" + chars[i]).getBytes();
            if (bytes.length == 2) {
                int[] ints = new int[2];
                ints[0] = bytes[0] & 0xff;
                ints[1] = bytes[1] & 0xff;
                if (ints[0] >= 0x81 && ints[0] <= 0xFE && ints[1] >= 0x40 && ints[1] <= 0xFE) {
                    isGB2312 = true;
                    break;
                }
            }
        }
        return isGB2312;
    }

    /**
     * 将内容写入文件里
     */
    public static synchronized void write(File file, String content) throws Exception {
        FileOutputStream fos = null;
        PrintStream ps = null;
        fos = new FileOutputStream(file, false);// 文件输出流	覆盖 默认为覆盖 可以不写false
        ps = new PrintStream(fos);
        ps.print(content); // 执行写操作
        fos.close();
        ps.close();    // 关闭流

//		System.out.println("内容已写入文件"+file.getName()+"！");
    }

    /**
     * 检测文件夹是否存在 如果不存在则创建
     * @param filePath
     */
    public static synchronized File checkDirectory(String filePath) {
        File file = new File(filePath);
        if(!file.exists()){
            //不存在则创建
            file.mkdirs();
        }
        return file;
    }
}
